package ssq.gamest.game

import java.util.HashMap
import java.util.LinkedList
import java.util.List
import java.util.Vector
import java.util.Comparator
import java.util.Collections

/**
 * 管理单张牌和牌组的大小, 也就是扑克游戏中<b>所有</b>的大小关系
 * 
 * @author s
 */
public class PokerOrderSettings
{
	final Poker game

	/**
	 * 牌组的大小
	 */
	public var patternOrder = new HashMap<Pair<Class<? extends PokerPattern>, Class<? extends PokerPattern>>, Integer>

	/**
	 * id->pattern class
	 */
	public var idPattern = new Vector<Class<? extends PokerPattern>>

	/**
	 * 牌型的拓扑排序
	 */
	public var patternTopologySort = new Vector<PokerPattern>
	public var importance = new HashMap<Class<? extends PokerPattern>, Double>

	/**
	 * 比当前id对应的牌型大的牌型id邻接表
	 */
	var biggerPatterns = new Vector<LinkedList<Integer>>

	/**
	 * 比当前id对应的牌型小的牌型id邻接表
	 */
	var smallerPatterns = new Vector<LinkedList<Integer>>

	/**
	 * 单张牌的大小
	 */
	public List<Integer> pointOrder
	public List<Color> colorOrder
	public boolean withColor = false
	public boolean colorFirst = false

	/**
	 * 规则相关
	 */
	public List<Color> someColors = new LinkedList<Color>()
	public List<Integer> somePoints = new LinkedList<Integer>()

	/**
	 * 在小端按从小到大的顺序保存两端都允许通过"++"连接的点数
	 */
	public List<Integer> twoEndian = new LinkedList<Integer>()

	public Vector<Integer> scanListByOrder
	public Vector<Integer> scanListByLiteral = new Vector(#[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])

	new(List<Integer> l, Poker game)
	{
		this.game = game
		setOrder(l)
	}

	new(List<Integer> li, List<Color> lc, boolean colorFirst, Poker game)
	{
		this.game = game
		setOrder(li, lc)
		this.colorFirst = colorFirst
	}

	/**
	 * 单张牌的大小
	 * 
	 * @param cards
	 */
	def void refreshOrder(List<PokerCard> cards)
	{
		for (PokerCard card : cards)
		{
			refreshOrder(card)
		}
	}

	def void refreshOrder(PokerCard card)
	{
		card.order = if(colorFirst)
		{
			pointOrder.indexOf(card.point) + (colorOrder.indexOf(card.color) << 4)
		}
		else
		{
			((pointOrder.indexOf(card.point) << 3) + ( if(withColor) colorOrder.indexOf(card.color) else 0)
			)
		}
	}

	/**
	 * 返回两种牌型的偏序比较结果. 如果是无法比较, 返回-2
	 * 
	 * @param p1
	 * @param p2
	 * @ p1>p2 ? 1 : p1=p2 ? 0 : p1<p2 ? -1 : -2
	 */
	def getOrder(Class<? extends PokerPattern> p1, Class<? extends PokerPattern> p2)
	{
		patternOrder.get(p1 -> p2) ?: -2
	}

	/**
	 * 会刷新scanListByOrder
	 */
	def setPointOrder(List<Integer> pointOrder)
	{
		this.pointOrder = pointOrder
		this.scanListByOrder = new Vector(pointOrder)

		if(twoEndian != null && !twoEndian.isEmpty)
		{
			scanListByOrder.addAll(0, twoEndian)
		}
		this
	}

	def setColorOrder(List<Color> colorOrder)
	{
		this.colorOrder = colorOrder
		this
	}

	def setSomeColors(List<Color> someColors)
	{
		this.someColors = someColors
		this
	}

	def setSomePoints(List<Integer> somePoints)
	{
		this.somePoints = somePoints
		this
	}

	def setTwoEndian(List<Integer> twoEndian)
	{
		this.twoEndian = twoEndian
		setPointOrder(pointOrder) // 刷新scanListByOrder
		this
	}

	/**
	 * 当花色不影响大小时调用
	 * 
	 */
	def setOrder(List<Integer> l)
	{
		withColor = false
		setPointOrder(l)
		this
	}

	/**
	 * 当花色也影响大小时调用
	 * 
	 */
	def setOrder(List<Integer> li, List<Color> lc)
	{
		withColor = true
		setPointOrder(li)
		colorOrder = lc

		this
	}

	/**
	 * 给牌型的偏序矩阵, 邻接表, 逆邻接表, 拓扑排序表初始化
	 */
	def PokerOrderSettings setPatternAndOrder(List<List<String>> paths)
	{
		var pathsVector = new Vector<Vector<Class<? extends PokerPattern>>>(paths.size())

		for (List<String> list : paths)
		{
			var tmp = new Vector<Class<? extends PokerPattern>>()
			pathsVector.add(tmp)

			for (String string : list)
			{
				try
				{
					if(string.equals("`others`"))
					{
						tmp.add(PokerPattern)
					}
					else
					{
						var clazz = Class.forName("ssq.gamest.game." + game.packageName + ".patterns." + string) as Class<? extends PokerPattern>
						tmp.add(clazz)

						if(!idPattern.contains(clazz))
						{
							idPattern.add(clazz)
							smallerPatterns.add(new LinkedList)
							biggerPatterns.add(new LinkedList)
							patternOrder.put(clazz -> clazz, 0)
						}
					}
				}
				catch(ClassNotFoundException e)
				{
					e.printStackTrace()
					System.exit(-1)
				}
			}
		}

		for (var iterator = pathsVector.iterator(); iterator.hasNext();)
		{
			var vector = iterator.next()

			for (var i = vector.size() - 1; i >= 0; i--)
			{
				var bigger = vector.get(i)

				for (var j = i - 1; j >= 0; j--)
				{
					var smaller = vector.get(j)

					if(smaller == PokerPattern) // bigger大于所有未与bigger定序的pattern
					{
						for (var k = 0; k < idPattern.size; k++)
						{
							var mayBeSmaller = idPattern.get(k)
							if(!patternOrder.containsKey(bigger -> mayBeSmaller))
							{
								add(bigger, mayBeSmaller)
							}
						}
					}
					else
					{
						add(bigger, smaller)
					}
				}
			}
		}

		var copyOfBiggerPatterns = new Vector<LinkedList<Integer>>(biggerPatterns.size)

		for (var i = 0; i < biggerPatterns.size; i++)
		{
			var tmp = biggerPatterns.get(i).clone as LinkedList<Integer>
			copyOfBiggerPatterns.add(tmp)
		}

		while(!isEmpty(copyOfBiggerPatterns))
		{
			for (Class<? extends PokerPattern> pattern : importance.keySet)
			{
				importance.put(pattern, importance.get(pattern) * 16)
			}

			var toBeCleared = new LinkedList<Class<? extends PokerPattern>>
			var mayBeCleared = new LinkedList<Class<? extends PokerPattern>>
			var maxDepth = -1
			for (var i = 0; i < copyOfBiggerPatterns.size; i++)
			{
				var item = copyOfBiggerPatterns.get(i)
				if(item != null && item.size == 0)
				{
					val pattern = idPattern.get(i)
					mayBeCleared.add(pattern)

					maxDepth = Math.max(smallerPatterns.get(i).size, maxDepth)
				}
			}
			
			var toBeAdded = new LinkedList<PokerPattern>
			for (Class<? extends PokerPattern> pattern : mayBeCleared)
			{
				if(smallerPatterns.get(idPattern.indexOf(pattern)).size == maxDepth)
				{
					toBeCleared.add(pattern)
                    toBeAdded.add(pattern.newInstance)
					importance.put(pattern, 8.0)
				}
			}
            
            try
            {
                
            Collections.sort(toBeAdded,new Comparator(){
                override compare(Object arg0, Object arg1) {
                    arg1.getClass.getDeclaredField("leastCards").getInt(null) - arg0.getClass.getDeclaredField("leastCards").getInt(null)
                }
                })
            }
            catch(Exception e)
            {
                e.printStackTrace
            }
//                println(toBeAdded)
            patternTopologySort.addAll(toBeAdded)

			if(toBeCleared.size == 0 && !isEmpty(copyOfBiggerPatterns))
			{
				throw new Exception("**********出现循环包含")
			}

			// println("to be cleared in this loop:")
			for (Class<? extends PokerPattern> item_ : toBeCleared)
			{

				// println(item_.name)
				copyOfBiggerPatterns.set(idPattern.indexOf(item_), null)

				for (LinkedList<Integer> item : copyOfBiggerPatterns)
				{
					if(item != null)
						item.remove(Integer.valueOf(idPattern.indexOf(item_)))
				}
			}
		}

		this
	}

	def isEmpty(Vector<LinkedList<Integer>> list2)
	{
		for (List list : list2)
		{
			if(list != null)
			{
				return false
			}
		}
		true
	}

	def void add(Class<? extends PokerPattern> bigger, Class<? extends PokerPattern> smaller)
	{
		var biggerIndex = idPattern.indexOf(bigger)
		var smallerIndex = idPattern.indexOf(smaller)

		patternOrder.put(bigger -> smaller, 1)
		patternOrder.put(smaller -> bigger, -1)

		smallerPatterns.get(biggerIndex).add(smallerIndex)
		biggerPatterns.get(smallerIndex).add(biggerIndex)
	}

	def getScanList(boolean byOrder)
	{
		if(byOrder)
		{
			scanListByOrder
		}
		else
		{
			scanListByLiteral
		}
	}
}
